<?php

/**
 *  订单管理
 */

namespace app\api\service;

use app\admin\service\LogisticsRules;
use app\admin\service\Warehouse as WarehouseAdmin;
use app\admin\service\ProductInventory;
use app\api\exception\ThrowException;
use app\api\model\Customer;
use app\api\model\Images;
use app\api\model\LogisticsOrderItem;
use app\api\model\Order as ModelOrder;
use app\api\model\OrderItem;
use app\api\model\LogisticsCompany;
use app\api\model\Product as ProductModel;
use app\api\model\Warehouse;
use app\api\model\WholesalOrderItem;
use app\api\service\CCNames as CCNamesService;
use app\api\service\ProductMerge as ProductMergeService;
use app\common\BusinessLog;
use app\common\Calculate;
use app\common\Common;
use app\common\RedisClient;
use app\facade\Basic;
use app\api\model\Carts as CartsModel;
use app\facade\Mail;
use think\facade\Db;
use think\facade\Lang;
use app\api\model\Address as AddressModel;
use app\api\model\OrderPayment as ModelOrderPayment;
use app\api\service\GoAffPro;
use think\facade\Log;
use app\api\service\Discount;
use app\common\service\CompleteNotificationService;
use app\admin\model\Inventory as InventoryModel;
use app\admin\model\ProductPrice as PriceModel;

class Order
{
    /**
     *  计算价格
     */
    public function calculatePrice($param)
    {
        $condition = [];
        $productPrice = new ProductPrice();
        if (isset($param['arrival_date']) && empty($param['arrival_date'])) {
            $param['arrival_date'] = null;
        }
        $condition[] = $param;
        $PriceList = $productPrice->getPrice($condition);
        $data = array_values($PriceList['data']);
        foreach ($data as $k=> $v){
            if($v['wid'] != $param['wid']){
                unset($data[$k]);
            }
        }
        return Basic::data(0, 'common.success', $data);
    }

    /**
     *  订单结算
     */
    public function checkout($param)
    {


        /* 获取用户类型 */
        $user_where[] = ['id', '=', $param['user_id']];
        $user_where[] = ['login_status', '=', 1];
        $user_where[] = ['is_del', '=', 0];
        $user = Customer::where($user_where)->field('id,role,email,is_advance')->find();
        if (!$user) {
            return Basic::data(0, 'common.userNotExist');
        }
        /* 判断商品 */
        if (count($param['product']) == 0) {
            return Basic::data(0, 'common.productDoesNotExist');
        }
        $condition = [];
        switch ($param['method']) {
            /* 购物车结算 */
            case 'cart':
                $result_cart = CartsModel::where('user_id', '=', $param['user_id'])
                    ->where('id', 'in', $param['product'])
                    ->field('id,product_id,warehouse_id,arrival_date,is_futures,quantity')
                    ->select();

                if (!$result_cart) {
                    return Basic::data(1, 'carts.cartNotExist');
                }
                $cart = $result_cart->toArray();
                foreach ($cart as $key => $item) {
                    $condition[$key]['id'] = $item['id'];
                    $condition[$key]['productid'] = $item['product_id'];
                    $condition[$key]['user_id'] = $param['user_id'];
                    $condition[$key]['wid'] = $item['warehouse_id'];
                    $condition[$key]['arrival_date'] = $item['arrival_date'];
                    $condition[$key]['is_futures'] = $item['is_futures'];
                    $condition[$key]['quantity'] = $item['quantity'];
                }
                break;

            /* 直接购买 */
            case 'buynow':
                $productMergeService = new ProductMergeService();
                $ccNamesService = new CCNamesService();
                $product_param = $param['product'];
                if (empty($product_param) || !is_array($product_param)) {
                    return Basic::data(1, 'order.productArray');
                }
                foreach ($product_param as $buy) {
                    $ccNameId = $ccNamesService->getCCNamesByIp($param['ip']);
                    try {
                        $result = $productMergeService->chooseInventoryDataByBatchAndCcnameId($buy['sku_id'], $buy['batch'], $ccNameId);
                    } catch (\Exception $e) {
                        return Basic::data(1, 'order.createOrderError', $e);
                    }
                    /* 判断库存数据是否存在 */
                    if (empty($result)) {
                        return Basic::data(1, 'order.createOrderError');
                    }
                    $inventory = $result;

                    $condition[] = [
                        'id' => $inventory['id'],
                        'productid' => $inventory['productid'],
                        'wid' => $inventory['wid'],
                        'user_id' => $param['user_id'],
                        'arrival_date' => $inventory['arrival_date'],
                        'is_futures' => $inventory['is_futures'],
                        'quantity' => $buy['quantity']
                    ];
                }
                break;
            default:
                return Basic::data(1, 'order.orderMethodError');
        }

        $productPrice = new ProductPrice();

        $PriceList = $productPrice->getPrice($condition);
        $PriceListNew = $productPrice->getPriceNew($condition,$param['lang']);
        if ($PriceList['code'] !== 0) {
            return Basic::data(1, 'common.productDoesNotExist');
        }
        $PriceListNew =$PriceListNew['data'];
        /* 获取商品信息 */
        $Product_ids = array_column($PriceList['data'], 'productid');
        $wids = array_column($condition, 'wid');
        $product_ids = array_unique($Product_ids);
        $product_where[] = ['id', 'in', $product_ids];

        $ProductReslut = ProductModel::with([
            'brand' => function ($query) {
                return $query->field('id,name,image');
            },
        ])->where($product_where)->field('id,cname,category,brand,condition,expiration_date,hashrate,computing_unit,power,photo,main_photo,describe,estimated_ship_date,weight')->select();
        $ProductReslut = $ProductReslut->toArray();
        foreach ($ProductReslut as &$product_photo) {
            if (empty($product_photo['main_photo']) && !empty($product_photo['photo'])) {
                $product_photo['main_photo'] = explode(',', $product_photo['photo'])[0];
            }
        }

        $photoidsArr =  array_column($ProductReslut, 'main_photo');
        $imageModel = new Images();
        $photoList = $imageModel->getImagesByIds($photoidsArr);

        // 将数组转换为以ID为下标的结构
        $photoList = array_column($photoList, null, 'id');

        $product = [];
        $common = new \app\api\service\Common();
        foreach ($ProductReslut as $item) {
            $key = $item['id'];
            $product[$key]['product_id'] = $item['id'];
            $product[$key]['cname'] =  $common->singleTranslate($item['cname'],$param['lang']);
            $product[$key]['brand_id'] = $item['brand']['id'] ?? null;
            $product[$key]['brand_name'] = $item['brand']['name'] ?? null;
            if($product[$key]['brand_name']){
                $product[$key]['brand_name'] =   $common->singleTranslate($product[$key]['brand_name'],$param['lang']);
            }
            $product[$key]['brand_image'] = $item['brand']['image'] ?? null;
            $product[$key]['condition'] = $item['condition'];
            $product[$key]['expiration_date'] = $item['expiration_date'];
            $product[$key]['hashrate'] = $item['hashrate'];
            $product[$key]['computing_unit'] = $item['computing_unit'];
            $product[$key]['power'] = $item['power'];
            $product[$key]['main_photo'] = $photoList[$item['main_photo']]['url'] ?? null;
            $product[$key]['describe'] = $item['describe'];
            $product[$key]['estimated_ship_date'] = $item['estimated_ship_date'];
            $product[$key]['weight'] = $item['weight'];
        }

        /* 组装商品列表 */
        foreach ($PriceList['data'] as &$value) {
            $key = $key = implode('_', [
                $value['productid'],
                $value['arrival_date'],
                $value['is_futures']
            ]);
            $item = $product[$value['productid']];
            $value = array_merge($value, $item);
            $value['warehouse_list'] = $PriceListNew[$key]['warehouse_list']??[];
        }


        //           print_r($product);
        //           die;


        //        if($carts === 0) {
        //            return Basic::data(1,'order.shoppingCartNotExist');
        //        }
        //
        //        if($carts !== count($ids)){
        //            return Basic::data(1,'order.shoppingCartIdsError');
        //        }


        //        $Carts = new Carts();
        //        $data = $Carts->CartsList($param);


        $data = [];
        $data['product'] = array_values($PriceList['data']);
        /* 收货地址 */
        $shipping_address = AddressModel::where('user_id', '=', $param['user_id'])->where('type', '=', 1)
            ->field('id,first_name,last_name,email,phone,address,is_default,remark,country_name,city_name,zip_code,state,company,address2')
            ->order('is_default desc,id desc')
            ->find();
        $data['shipping_address'] = $shipping_address ?? null;
        $data['address_id'] = $shipping_address->id ?? null;

        /* 账单地址 */
        $billing_address = AddressModel::where('user_id', '=', $param['user_id'])->where('type', '=', 2)
            ->field('id,first_name,last_name,email,phone,address,is_default,remark,country_name,city_name,zip_code,state,company,address2')
            ->order('is_default desc,id desc')
            ->find();

        $data['billing_address'] = $billing_address ?? null;
        $data['billing_address_id'] = $billing_address->id ?? null;
        $ModelOrder = new ModelOrder();

        /* 物流方式 */
        $data['delivery_method'] = $ModelOrder->getAttributes('delivery_method');
        foreach ($data['delivery_method'] as &$delivery){
            $delivery['label'] = $common->singleTranslate($delivery['label'],$param['lang']);
        }
        $data['delivery_method_id'] = 1;

        /* 物流时效 */
        $data['prescription_method'] = $ModelOrder->getAttributes('prescription');
        $data['prescription'] = 1;

        /* 贸易条款 */
        $data['delivery_terms_method'] = $ModelOrder->getAttributes('delivery_terms');
        $data['delivery_terms'] = 1;

        /* 付款方式 */
        $data['pay_terms_method'] = $ModelOrder->getAttributes('pay_terms');
        $data['pay_terms'] = 0;

        /* 是否采购订单 */
        $data['is_wholesal'] = 0;

        /* 支付方式 */
        $PaymentMethod = new PaymentMethod();
        $data['payment_method'] = $PaymentMethod->getPaymentMethodList($param);
        $data['payment_method_id'] = $data['payment_method'][0]['id'];
        foreach ($data['payment_method'] as &$payment_method_list)
        {
            $payment_method_list['name'] = $common->singleTranslate($payment_method_list['name'],$param['lang']);
        }

        /* ids */
        $param['ids'] = $product_ids;

        //        /* 自提地址 */
        //       $warehouse = $this->getwarehouseAddress($param);
        //
        //       print_r($warehouse);
        //       die;
        //
        //       if( $warehouse['code'] == 0 ) {
        //           $data['pickup_address'] = $warehouse['data'];
        //       } else {
        //           $data['pickup_address'] = '';
        //       }


        /* 获取用户Emdil */
        $data['billing_email'] = $user->email;
        if ($user->is_advance == 0) {
            $data['is_advance'] = 0;
        }

        /* 转转支付信息 */
        $data['payment_information'] = $PaymentMethod->getPaymentInformation();

        /* 物流费用 */
        $data['shipping_amount'] = 0.00;
        $data['warehouse'] = Warehouse::where('id', 'in', $wids)->field('id,pickup_address')->select()->toArray();
        /* 是否包含中国地区商品 */
        //$data['continent'] = $data['continent'];

        /* 总结 */
        //$data['total_amount'] = $data['cart_amount'];

        return Basic::data(0, 'common.success', $data);
    }

    /**
     * 获取商品信息
     *
     */
    public function getProductPriceInfo($condition)
    {
        $productPrice = new ProductPrice();
        $PriceList = $productPrice->getPrice($condition);

        if ($PriceList['code'] !== 0) {
            return [];
        }
        /* 获取商品信息 */
        $Product_ids = array_column($PriceList['data'], 'productid');
        $product_ids = array_unique($Product_ids);
        $product_where[] = ['id', 'in', $product_ids];

        $ProductReslut = ProductModel::with([
            'brand' => function ($query) {
                return $query->field('id,name,image');
            },

        ])->where($product_where)->field('id,cname,category,brand,condition,expiration_date,hashrate,free_shipping,apply_rules,computing_unit,power,main_photo,type,photo,describe,estimated_ship_date,weight')->select();

        $ProductReslut = $ProductReslut->toArray();
        foreach ($ProductReslut as &$product_photo) {
            if (empty($product_photo['main_photo']) && !empty($product_photo['photo'])) {
                $product_photo['main_photo'] = explode(',', $product_photo['photo'])[0];
            }
        }

        $photoidsArr =  array_column($ProductReslut, 'main_photo');
        $imageModel = new Images();
        $photoList = $imageModel->getImagesByIds($photoidsArr);

        // 将数组转换为以ID为下标的结构
        $photoList = array_column($photoList, null, 'id');
        $product = [];
        foreach ($ProductReslut as $item) {
            $key = $item['id'];
            $product[$key]['product_id'] = $item['id'];
            $product[$key]['cname'] = $item['cname'];
            $product[$key]['brand_id'] = $item['brand']['id'] ?? null;
            $product[$key]['brand_name'] = $item['brand']['name'] ?? null;
            $product[$key]['brand_image'] = $item['brand']['image'] ?? null;
            $product[$key]['condition'] = $item['condition'];
            $product[$key]['expiration_date'] = $item['expiration_date'];
            $product[$key]['hashrate'] = $item['hashrate'];
            $product[$key]['computing_unit'] = $item['computing_unit'];
            $product[$key]['power'] = $item['power'];
            $product[$key]['main_photo'] = $photoList[$item['main_photo']]['url'] ?? null;
            $product[$key]['describe'] = $item['describe'];
            $product[$key]['estimated_ship_date'] = $item['estimated_ship_date'];
            $product[$key]['weight'] = $item['weight'];
            $product[$key]['free_shipping'] = $item['free_shipping'];
            $product[$key]['apply_rules'] = $item['apply_rules'];
        }

        /* 组装商品列表 */
        foreach ($PriceList['data'] as &$value) {
            $item = $product[$value['productid']];
            $value = array_merge($value, $item);
        }
        return array_values($PriceList['data']);
    }

    public function create($param)
    {
        $where['user_id'] = $param['user_id'];
        $conditions = $param['product'];

        if (count($conditions) === 0) {
            return Basic::data(1, 'order.productRequire');
        }

        // 参数验证
        $order_num = 0;
        foreach ($conditions as $key => $item) {
            if (!is_numeric($item['productid'])) {
                return Basic::data(1, 'KEY:' . $key . ' productid 参数错误');
            }
            if (!is_numeric($item['wid'])) {
                return Basic::data(1, 'KEY:' . $key . ' wid 参数错误');
            }
            if (!in_array($item['is_futures'], [0, 1, 2])) {
                return Basic::data(1, 'KEY:' . $key . ' is_futures 参数错误');
            }
            if (!is_numeric($item['quantity']) || $item['quantity'] <= 0) {
                return Basic::data(1, 'KEY:' . $key . ' quantity 参数错误');
            }
            $order_num += $item['quantity'];
        }

        $param['order_num'] = $order_num;
        return ($param['origin'] == 2)
            ? $this->createOrderBuyNow($param)
            : $this->createOrderFromCart($param);
    }

    private function createCommonOrderLogic(&$param, $productData, $logisticsCondition, $isOversold = false)
    {
        $checkCodeResult = null;
        # 订单基础价格
        $ins_order_data = $this->buildOrderBaseData($param, $productData);
        #自提地址 快递地址 处理
        $isSendSelf = $this->processOrderAddress($param, $ins_order_data);
        # 支付方式
        $ins_order_data = $this->processOrderStatus($param, $ins_order_data, $isOversold);
        #计算运费 处理订单价格
        $rules = $this->calculateOrderPrices($param, $ins_order_data, $productData, $logisticsCondition);
        #订单优惠信息  处理优惠券
        $this->processOrderDiscounts($param, $ins_order_data, $productData,$checkCodeResult);

        #生成订单
        Db::startTrans();
        try {
            $result = $this->createOrderRecords($param, $ins_order_data, $productData, $isSendSelf, $isOversold,$rules,$checkCodeResult);
            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();
            return Basic::data(1, 'order.createOrderError', $e);
        }

        $this->sendOrderNotifications($param, $ins_order_data['order_no'], $isSendSelf);
        return (new OrderPayment())->goPay($result, $param);
    }

    private function buildOrderBaseData(&$param, $productData)
    {
        $total_first_leg_logistics_fee = 0;
        foreach ($param['product'] as $value){
            $total_first_leg_logistics_fee = bcadd($total_first_leg_logistics_fee, (bcmul($value['first_leg_logistics_fee'], $value['quantity'], 2)), 2);
        }
        $common = new Common();
        $return = [
            'order_no' => $common->generateOrderNoNew(2,0),
            'user_id' => $param['user_id'],
            'first_leg_logistics_fee' => $total_first_leg_logistics_fee,
            'create_time' => date("Y-m-d H:i:s"),
            'order_type' => 1,
            'pay_terms' => $param['pay_terms'],
            'order_num' => $productData['total_count'],
            'notes' => $param['notes'] ?? '',
            'source' => 1,
            'is_del' => 0,
            'pay_status' => 1,
            'order_weight' => 0,
            'advance_amount' => 0.00,
            'logistics_fee' => 0.00,
            'pay_amount' => 0.00,
            'status' => 10
        ];
        $redis = new RedisClient();
        $key = 'bulkAddcart_user_id:'.$param['user_id'];
        $is_bulk = $redis->get($key);
        if($productData['is_cart'] && $is_bulk){
           $user = Customer::where('id',$param['user_id'])->find();
            $return['owner'] = $user->owner;
            $return['partner'] = $user->partner;
            $redis->delete($key);
        }
        return $return;
    }

    private function processOrderAddress(&$param, &$ins_order_data)
    {
        $isSendSelf = true;

        if ($param['is_wholesal'] == 1) {
            $ins_order_data['delivery_method'] = $param['delivery_method'];

            if ($param['delivery_method'] == 0) {
                if ($param['warehouse_code']) {
                    $isSendSelf = false;
                }

                $ins_order_data['pickup_name'] = $param['pickup_name'];
                $ins_order_data['pickup_phone'] = $param['pickup_phone'];
                $ins_order_data['pickup_passport'] = $param['pickup_passport'];
                $ins_order_data['pickup_vehicle'] = $param['pickup_vehicle'];
                $ins_order_data['warehouse_code'] = $param['warehouse_code'];
                $ins_order_data['pickup_code'] = generateUniqueString();
                $ins_order_data['pickup_address'] = '';
            } elseif ($param['delivery_method'] == 2){
                $isSendSelf = false;
                $ins_order_data['pickup_name'] = $param['pickup_name'];
                $ins_order_data['pickup_phone'] = $param['pickup_phone'];
                $ins_order_data['pickup_passport'] = $param['pickup_passport'];
                $ins_order_data['warehouse_code'] = $param['warehouse_code'];
                $ins_order_data['pickup_vehicle'] = $param['pickup_vehicle'];
            }else {
                $isSendSelf = false;
                if (!empty($param['address_id'])) {
                    $this->processShippingAddress($param, $ins_order_data);
                }
                $ins_order_data['delivery_terms'] = $param['delivery_terms'];
                $ins_order_data['prescription'] = $param['prescription'];
            }

            if (!empty($param['billing_address_id'])) {
                $this->processBillingAddress($param, $ins_order_data);
            }

            $ins_order_data['order_category'] = 'order';
        } else if ($param['is_wholesal'] == 2) {
            $ins_order_data['order_category'] = 'wholesal';
            $isSendSelf = false;
        }

        return $isSendSelf;
    }

    private function processShippingAddress(&$param, &$ins_order_data)
    {
        $address = AddressModel::where([
            ['id', '=', $param['address_id']],
            ['user_id', '=', $param['user_id']],
            ['type', '=', 1]
        ])
            ->field('id,first_name,last_name,email,phone,address,address2,country_id,remark,city_id,country_name,city_name,zip_code,state,company')
            ->find();

        if (!$address) {
            throw new Exception('order.addressDoesNotExist');
        }

        $fields = [
            'address_id' => 'id',
            'first_name' => 'first_name',
            'last_name' => 'last_name',
            'email' => 'email',
            'phone' => 'phone',
            'address' => 'address',
            'address2' => 'address2',
            'country_id' => 'country_id',
            'city_id' => 'city_id',
            'country_name' => 'country_name',
            'city_name' => 'city_name',
            'zip_code' => 'zip_code',
            'delivery_remark' => 'remark',
            'state' => 'state',
            'company' => 'company'
        ];

        foreach ($fields as $target => $source) {
            $ins_order_data[$target] = $address->$source;
        }
    }

    private function processBillingAddress(&$param, &$ins_order_data)
    {
        $address = AddressModel::where([
            ['id', '=', $param['billing_address_id']],
            ['user_id', '=', $param['user_id']]
        ])
            ->field('id,user_id,first_name,last_name,email,phone,address,remark,country_name,city_name,zip_code,state,company,address2')
            ->find();

        if (!$address) {
            throw new \Exception('order.billingAddressNotExist');
        }

        $billingFields = [
            'billing_address_id' => 'id',
            'billing_first_name' => 'first_name',
            'billing_last_name' => 'last_name',
            'billing_email' => 'email',
            'billing_phone' => 'phone',
            'billing_address' => 'address',
            'billing_address2' => 'address2',
            'billing_country_id' => 'country_id',
            'billing_city_id' => 'city_id',
            'billing_country_name' => 'country_name',
            'billing_city_name' => 'city_name',
            'billing_zip_code' => 'zip_code',
            'billing_state' => 'state',
            'billing_remark' => 'remark',
            'billing_company' => 'company'
        ];

        foreach ($billingFields as $target => $source) {
            $ins_order_data[$target] = $address->$source;
        }
    }

    private function processOrderStatus(&$param, $ins_order_data, $isOversold)
    {
        if ($param['is_wholesal'] != 1 && $param['is_wholesal'] != 2) {
            throw new Exception('order.isWholesalIn');
        }

        if (!is_null($param['payment_method'])) {
            $PaymentMethod = new PaymentMethod();
            $paymentMethodItem = $PaymentMethod->getPaymentMethodItem($param['payment_method']);
            $ins_order_data['payment_method'] = $paymentMethodItem['id'] ?? 0;
            $ins_order_data['pay_method_name'] = $paymentMethodItem['name'] ?? '';
        }

        if ($isOversold) {
            $ins_order_data['status'] = 20;
            $ins_order_data['review_node'] = 1;
        }

        return $ins_order_data;
    }

    private function calculateOrderPrices(&$param, &$ins_order_data, $productData, $logisticsCondition)
    {
        $rules = [];
        $ins_order_data['product_total_amount'] = $productData['total_amount'];
        $ins_order_data['product_total_original_amount'] = $productData['product_original_amount'];

        if (2 == $param['role']) { // 经销商原始商品价格使用一级折扣价格
            $product_total_original_amount = 0;

            foreach ($productData['list'] as $key => $item) {

                $single_product_total_original_amount = $this->getProductOriginalPrice(
                    $param['role'] == 2 ? 'distributor' : 'user',
                    $item['arrival_date'],
                    $item['is_futures'],
                    $item['wid'],
                    $item['productid'],
                    214
                );
                $product_total_original_amount += $single_product_total_original_amount * $item['quantity'];
    
            }
            if ($product_total_original_amount > 0) {
                $ins_order_data['product_total_original_amount'] = $product_total_original_amount;
            }
        }

        if ($param['delivery_method'] == 1) {
            $feeParam = [
                'product' => $logisticsCondition,
                'terms' => $param['delivery_terms'],
                'address_id' => $param['address_id'],
                'prescription' => $param['prescription'],
            ];
            $fee = (new Logistics())->fee($feeParam);
            if (isset($fee['code']) && $fee['code'] == 0) {
                $ins_order_data['logistics_fee'] = $fee['data']['logistics_fee'];
                $rules = array_column($fee['data']['product_list'] ,null,'id');
            }
        }

        $ins_order_data['total_amount'] = Calculate::pricecalc(
            $ins_order_data['product_total_amount'],
            '+',
            $ins_order_data['logistics_fee'],
            2
        );
        $ins_order_data['total_amount'] = Calculate::pricecalc(
            $ins_order_data['total_amount'],
            '+',
            $ins_order_data['first_leg_logistics_fee'],
            2
        );
        return $rules;
    }

    private function processOrderDiscounts(&$param, &$ins_order_data, &$productData,&$checkCodeResult=null)
    {
        if (!empty($param['discount_code'])) {
            $Discount = new Discount();
            $checkCodeParams = [
                'user_id' => $param['user_id'],
                'role' => $param['role'],
                'code' => $param['discount_code'],
                'product_list' => array_map(function ($item) {
                    return [
                        'id' => $item['productid'] ?? $item['product_id'],
                        'number' => $item['quantity'],
                        'price' => $item['sales_price'],
                    ];
                }, $productData['list'])
            ];

            $checkCodeResult = $Discount->checkCode($checkCodeParams);

            if ($checkCodeResult['code'] === 0 &&
                $checkCodeResult['data']['is_effective'] &&
                $checkCodeResult['data']['discount_id'] > 0)
            {
                $discount = $checkCodeResult['data'];
                $ins_order_data['total_amount'] = max(0, $ins_order_data['total_amount'] - $discount['total_discount']);
                $ins_order_data['product_total_amount'] = max(0, $ins_order_data['product_total_amount'] - $discount['total_discount']);

                $discountProducts = array_column($discount['product_list'], 'price', 'id');
                $productData['list'] = array_map(function ($item) use ($discountProducts) {
                    $key = $item['productid'] ?? $item['product_id'];
                    if (isset($discountProducts[$key])) {
                        $item['sales_price'] = $discountProducts[$key];
                    }
                    return $item;
                }, $productData['list']);
            } else {
                Log::error('优惠券验证失败: ' . ($checkCodeResult['message'] ?? '') . ' 验证参数: ' . json_encode($checkCodeParams));
            }
        }
    }

    private function createOrderRecords(&$param, $ins_order_data, $productData, &$isSendSelf, $isOversold,$rules=[],$checkCodeResult)
    {
        $result = ModelOrder::create($ins_order_data);
        if (!$result) {
            throw new Exception('普通订单表创建失败');
        }


        $itemList = [];
        foreach ($productData['list'] as $key => $item) {
            #exceptionstatus
            $exceptionstatus = null;
            if ($param['delivery_method'] == 1) {
                if(isset($rules[$item['productid']]['matched_rule']) && $rules[$item['productid']]['matched_rule'] === false){
                    $exceptionstatus = 2;
                    $result->exceptionstatus = $exceptionstatus;
                    $result->save();
                }
            }
            $original_price = $this->getProductOriginalPrice(
                $param['role'] == 2 ? 'distributor' : 'user',
                $item['arrival_date'],
                $item['is_futures'],
                $item['wid'],
                $item['productid'],
                214
            );
            $first_leg_logistics_fee = 0;
            foreach ($param['product'] as $p){
                if($p['productid'] == $item['productid']){
                    $first_leg_logistics_fee =  $p['first_leg_logistics_fee'];
                }
            }

            $itemData = [
                'user_id' => $result->user_id,
                'order_id' => $result->id,
                'first_leg_logistics_fee' => $first_leg_logistics_fee,
                'product_id' => $item['productid'] ?? $item['product_id'],
                'warehouse_id' => $item['wid'] ?? $item['warehouse_id'],
                'original_price' => $original_price,
                'exceptionstatus' => $exceptionstatus,
                'actual_price' => $item['sales_price'],
                'is_futures' => $item['is_futures'],
                'create_time' => date('Y-m-d H:i:s'),
                'quantity' => $item['quantity'],
                'pending_quantity' => $item['quantity'],
                'arrival_date' => $item['arrival_date'] ?? null,
                'real_arrival_date' => $item['real_arrival_date'] ?? null,
                'free_shipping' => $item['free_shipping'] ?? 0,
                'apply_rules' => $item['apply_rules'] ?? 0,
                'purchase_price' => $item['purchase_price'] ?? ($item['inventory']['items'][0]['purchase_price'] ?? null),
                'purchase_currency' => $item['purchase_currency'] ?? ($item['inventory']['items'][0]['purchase_currency'] ?? null),
                'transaction_currency_id' => 214,
                'price_selected_currency' => $item['sales_price']
            ];

            if (($item['is_futures'] ?? 0) != 0) {
                $isSendSelf = false;
            }

            if ($isOversold || (isset($item['inventory']['exceptionstatus']) && $item['inventory']['exceptionstatus'] == 1)) {
                $itemData['exceptionstatus'] = 1;
            }

            $itemList[] = $itemData;
        }
        if (!OrderItem::insertAll($itemList)) {
            throw new \Exception('普通订单明细表创建失败');
        }

        // 清除购物车（仅购物车流程）
        if (isset($productData['is_cart']) && $productData['is_cart']) {
            $carts = new Carts();
            if (!$carts->delCartById($param)) {
                throw new Exception('清除购物车失败');
            }
        }

        // 日志记录
        $Business = new BusinessLog();
        $Business->logOperation($result->id, 'order', '创建订单', $result->order_no);

        // 客户阶段自动维护
        $this->autoUserStage($result);

        // 联盟营销
        $this->createGoAffProOrder($result, $itemList, $checkCodeResult ?? null, $param['discount_code'] ?? null);

        return $result;
    }

    /**
     * @describe 获取商品原价
     * @author: Bobo
     * @date: 2025-07-15 14:04:48 
     * @param [string] $role 角色
     * @param [string] $arrival_date 到货日期
     * @param [int] $is_futures 是否期货
     * @param [int] $wid 仓库id
     * @param [int] $productid 商品id
     * @param [int] $transactionCurrencyId 交易货币id
     * @return float
     */
    public function getProductOriginalPrice($role, $arrival_date, $is_futures, $wid, $productid, $transactionCurrencyId)
    {

        try {
            $inventoryInfo = InventoryModel::getInventoryInfoByFourElements($arrival_date, $wid, $is_futures, $productid);

            $price = PriceModel::getPriceFromInventory($inventoryInfo['id'], $wid, $transactionCurrencyId);

            $original_price = array_reduce($price['discount'], function ($carry, $item) {
                return $item['level'] == 1 ? $item['price'] : $carry;
            }, 0);

            if ($role == 'distributor') {
                return $original_price;
            } else {
                return 0;
            }
        } catch (\Throwable $th) {
            Log::error('获取商品原价失败: ' . $th->getMessage() . ' file:' . $th->getFile() . ' line:' . $th->getLine() . ' role:' . $role . ' arrival_date:' . $arrival_date . ' is_futures:' . $is_futures . ' wid:' . $wid . ' productid:' . $productid . ' transactionCurrencyId:' . $transactionCurrencyId);
            return 0;
        }
    }

    private function sendOrderNotifications(&$param, $order_no, $isSendSelf)
    {
        Mail::send('order_success', ['user_id' => $param['user_id'], 'order_no' => $order_no]);
        if ($isSendSelf) {
            Mail::send('self_pickup', ['user_id' => $param['user_id'], 'order_no' => $order_no]);
        }
    }

    /*==================== 特定订单类型方法 ====================*/

    // === 新增：提取核心计算逻辑到私有方法 ===
    private function calculateProductData($condition)
    {
        $productInfo = $this->getProductPriceInfo($condition);
        $total_amount = 0;
        $original_amount = 0;
        $order_num = 0;

        foreach ($productInfo as $item) {
            $line_total = Calculate::pricecalc($item['quantity'], '*', $item['sales_price'], 2);
            $line_original_total = Calculate::pricecalc($item['quantity'], '*', $item['price'], 2);
            $total_amount = Calculate::pricecalc($total_amount, '+', $line_total, 2);
            $original_amount = Calculate::pricecalc($original_amount, '+', $line_original_total, 2);
            $order_num += $item['quantity'];
        }

        return [
            'list' => $productInfo,
            'total_count' => $order_num,
            'total_amount' => $total_amount,
            'product_original_amount' => $original_amount
        ];
    }

// 原立即购买方法保持不变（仅调用提取的方法）
    public function createOrderBuyNow($param)
    {
        $logisticsCondition = [];
        $condition = [];

        foreach ($param['product'] as $item) {
            $condition[] = [
                'id' => '',
                'productid' => $item['productid'],
                'wid' => $item['wid'],
                'user_id' => $param['user_id'],
                'arrival_date' => $item['arrival_date'],
                'is_futures' => $item['is_futures'],
                'quantity' => $item['quantity']
            ];
            $logisticsCondition[] = [
                'id' => $item['productid'],
                'quantity' => $item['quantity'],
                'wid' => $item['wid'],
            ];
        }

        // === 修改点1：调用提取的计算方法 ===
        $productData = $this->calculateProductData($condition);
        $productData['is_cart'] = false;

        return $this->createCommonOrderLogic($param, $productData, $logisticsCondition, false);
    }

// 原购物车方法保持不变（仅调用提取的方法）
    public function createOrderFromCart($param)
    {
        $logisticsCondition = [];
        $condition = [];

        foreach ($param['product'] as $item) {
            $condition[] = [
                'id' => '',
                'productid' => $item['productid'],
                'wid' => $item['wid'],
                'user_id' => $param['user_id'],
                'arrival_date' => $item['arrival_date'],
                'is_futures' => $item['is_futures'],
                'quantity' => $item['quantity']
            ];
            $logisticsCondition[] = [
                'id' => $item['productid'],
                'quantity' => $item['quantity'],
                'wid' => $item['wid'],
            ];
        }
        // === 修改点4：调用提取的计算方法 ===
        $productData = $this->calculateProductData($condition);
        $productData['is_cart'] = true;

        return $this->createCommonOrderLogic($param, $productData, $logisticsCondition);
    }

    /**
     * 创建 GoAffPro 订单
     * @param object $order 订单对象
     * @param array $orderItems 订单项
     * @param array|null $discountResult 优惠券验证结果
     * @param string|null $discountCode 优惠券代码
     * @return array|void
     */
    protected function createGoAffProOrder($order, $orderItems, $discountResult = null, $discountCode = null)
    {
        // 如果没有推广信息，只处理优惠券记录
        if (!isset($_SERVER['HTTP_X_GOAFFPRO_AFFINFO'])) {
            // 检查优惠券信息是否有效
            if ($discountResult && $this->isValidDiscount($discountResult)) {
                $this->recordDiscountUsage($order->id, $order->user_id, null, null, $discountResult['data']['discount_id'], $discountCode);
            }
            return;
        }
        if ($order->product_total_amount != 0) {
            // 获取商品和客户信息
            $product_info = ProductModel::where('id', 'in', array_column($orderItems, 'product_id'))
                ->where('is_del', 0)
                ->field('id,cname')
                ->select()
                ->toArray();

            $customer = Customer::where('id', $order->user_id)
                ->field('id,cusname,first_name,last_name,email,phone')
                ->find();

            // 构建订单数据
            $data = [
                'id' => $order->id,
                'number' => $order->order_no,
                'total' => $order->total_amount,
                'subtotal' => $order->product_total_amount,
                'shipping' => $order->logistics_fee,
                'customer' => [
                    'id' => $customer->id,
                    'name' => (!empty($customer->first_name) || !empty($customer->last_name)) ?
                        $customer->first_name . ' ' . $customer->last_name :
                        $customer->cusname,
                    'email' => $customer->email,
                    'phone' => $customer->phone,
                ],
                'line_items' => array_map(function ($item) use ($product_info) {
                    $product = array_filter($product_info, function ($product) use ($item) {
                        return $product['id'] == $item['product_id'];
                    });
                    $product = array_shift($product);
                    return [
                        'product_id' => $item['product_id'] ?? '',
                        'name' => $product['cname'] ?? '',
                        'quantity' => $item['quantity'] ?? '',
                        'price' => $item['price_selected_currency'] ?? '',
                    ];
                }, $orderItems)
            ];

            // 创建 GoAffPro 订单
            $GoAffPro = new GoAffPro();
            $createResult = $GoAffPro->createAffiliateOrder($_SERVER['HTTP_X_GOAFFPRO_AFFINFO'], $data);
        }

        // 处理优惠券记录
        if ((isset($createResult) && $createResult['code'] == 0) || ($discountResult && $this->isValidDiscount($discountResult))) {
            $this->recordDiscountUsage(
                $order->id,
                $order->user_id,
                $createResult['data']['id'] ?? null,
                $createResult['data']['affiliate_id'] ?? null,
                $discountResult['data']['discount_id'] ?? null,
                $discountCode
            );
        }
    }

    /**
     * 检查优惠券结果是否有效
     * @param array $discountResult
     * @return bool
     */
    private function isValidDiscount($discountResult)
    {
        return isset($discountResult['code'])
            && $discountResult['code'] === 0
            && isset($discountResult['data']['is_effective'])
            && $discountResult['data']['is_effective']
            && isset($discountResult['data']['discount_id'])
            && $discountResult['data']['discount_id'] > 0;
    }
    /**
     * 记录优惠券使用
     */
    protected function recordDiscountUsage($orderId, $userId, $affOrderId, $affiliateId, $discountId, $discountCode)
    {
        if (!$discountId) { // 优惠券id 无效，不要写入券码
            $discountCode = null;
        }
        $Discount = new Discount();
        $Discount->writCouponUsageRecord($orderId, $userId, $affOrderId, $affiliateId, $discountId, $discountCode);
    }

    /**
     *   客户阶段自动维护
     */
    public function autoUserStage($order)
    {
        $customer = Customer::where(['id' => $order->user_id])->field('id,stage')->find();

        if ($customer->stage < 2) {
            $customer->stage = 2;
            $customer->save();
        }
    }
    /**
     *  列表
     */
    public function list($param)
    {
        $where[] = ['user_id', '=', $param['user_id']];
        //        $where[] = ['order_category','=','order'];

        if (!empty($param['search_value'])) {
            $where[] = ['order_no', '=', trim($param['search_value'])];
        }

        switch ($param['status']) {
            case '10': // 审核中
                $where[] = ['status', 'in', '10,21'];
                break;
            case '20': // 审核中
                $where[] = ['status', '=', '20'];
                break;
            case '30': // 待收货
                $where[] = ['status', '=', '30'];
                break;
            case '50': // 已签收
                $where[] = ['status', 'in', '40,50'];
                break;
            case '70': // 已取消
                $where[] = ['status', '=', '70'];
                break;
            case '100': // 已完成
                $where[] = ['status', '=', '100'];
                break;
            default:
        }

        $result = ModelOrder::with([
            'item' => function ($query) {
                $query->with([
                    'product' => function ($query) {
                        return $query->with([
                            'brand' => function ($query) {
                                return $query->field('id,name,image');
                            },
                            'category' => function ($query) {
                                return $query->field('id,name');
                            },

                        ])->field('id,cname,category,brand,condition,expiration_date,hashrate,computing_unit,power,main_photo,photo,type,describe,estimated_ship_date,weight');
                    },
                    'inventory' => function ($query) {
                        return $query->field('id,name');
                    },
                    'warehouse' => function ($query) {
                        return $query->field('id,show_name as name');
                    }
                ])->where('is_del', '=', 0)
                    ->field('id,order_id,product_id,warehouse_id,original_price,actual_price,is_futures,quantity,create_time,arrival_date,is_futures');
            }
        ])
            ->field('id,order_no,user_id,order_num,order_type,first_name,last_name,create_time,country_name,city_name,pay_method_name,total_amount,pay_amount,pay_status,notes,status,pay_terms,order_weight,logistics_fee,source,delivery_method,tax_package,tax_fee,order_num')
            ->where($where)
            ->order('id DESC')
            ->paginate($param['listRows']);

        $result = $result->toArray();
        if ($result['total'] == 0) {
            unset($result['data']);
            $result['list'] = [];
            return Basic::data(0, 'common.success', $result);
        }

        $order = [];
        #翻译支持语言
        $common = new \app\api\service\Common();
        $photoidsArr = [];
        $photoList = [];
        foreach ($result['data'] as $datum){
            if($datum['item']){
                foreach ($datum['item'] as $productData){
                    if(!empty($productData['product']['main_photo']) ){
                        $photoidsArr[]=$productData['product']['main_photo'];
                    }
                    if ($productData['product']['type'] == 2 && !empty($productData['product']['photo'])) {
                        $photoidsArr[] = explode(',', $productData['product']['photo'])[0];
                    }
                }
            }
        }

        $imageModel = new Images();
        if($photoidsArr){
            $photoList = $imageModel->getImagesByIds($photoidsArr);

            // 将数组转换为以ID为下标的结构
            $photoList = array_column($photoList, null, 'id');
        }

        foreach ($result['data'] as $key => $value) {

            $order[$key]['id'] = $value['id'];
            $order[$key]['order_no'] = $value['order_no'];
            $order[$key]['order_num'] = $value['order_num'];
            $order[$key]['order_type'] = $value['order_type'];
            $order[$key]['first_name'] = $value['first_name'];
            $order[$key]['last_name'] = $value['last_name'];
            $order[$key]['create_time'] = $value['create_time'];
            $order[$key]['country_name'] = $value['country_name'];
            $order[$key]['city_name'] = $value['city_name'];
            $order[$key]['pay_method_name'] = $value['pay_method_name'];
            $order[$key]['total_amount'] = $value['total_amount'];
            $order[$key]['pay_amount'] = $value['pay_amount'];
            $order[$key]['pay_status'] = $value['pay_status'];
            $order[$key]['status'] = $value['status'];

            $order[$key]['status_text'] = $value['status_text'];
            # 翻译
            if ($order[$key]['status_text']) {
                $tran = md5($order[$key]['status_text']);
                $translate = [
                    'content' => json_encode([$tran => $order[$key]['status_text']]),
                    'target_language' => $param['lang'],
                ];
                $tran_return = $common->translate($translate);
                $order[$key]['status_text'] = $tran_return['data'][$tran] ?? $order[$key]['status_text'];
            }
            $order[$key]['logistics_fee'] = $value['logistics_fee'];
            $order[$key]['source'] = $value['source'];
            $order[$key]['tax_fee'] = $value['tax_fee'];

            /* 商品 */
            $order_item = [];
            foreach ($value['item']  as $k => $item) {

                $k = implode('_', [
                    $item['product_id'],
                    $item['warehouse_id'],
                    $item['arrival_date'],
                    $item['is_futures']
                ]);

                /* 合并 */
                if (isset($order_item[$k])) {
                    $order_item[$k]['quantity'] = Calculate::pricecalc($order_item[$k]['quantity'], '+', $item['quantity'], 0);
                    continue;
                }

                $order_item[$k]['id'] = $item['id'];
                $order_item[$k]['original_price'] = $item['original_price'];
                $order_item[$k]['actual_price'] = $item['actual_price'];
                $order_item[$k]['is_futures'] = $item['is_futures'];
                $order_item[$k]['quantity'] = $item['quantity'];
                $order_item[$k]['product_id'] = $item['product_id'];

                /* 商品详情 */
                if (!empty($item['product'])) {

                    $order_item[$k]['name'] = $item['product']['cname'];

                    /* 分类 */
                    if (!empty($item['product']['category'])) {
                        $order_item[$k]['category_id'] = $item['product']['category']['id'];
                        $order_item[$k]['category_name'] = $item['product']['category']['name'];
                    }

                    /* 缩略图 */
                    if (!empty($item['product']['photo']) && $item['product']['type'] == 2) {
                        $photoKey = explode(',',$item['product']['photo'])[0];
                        $order_item[$k]['thumb'] =$photoList[$photoKey]['url'] ?? '';
                    }
                    /* 缩略图 */
                    if (!empty($item['product']['main_photo'])) {
                        $order_item[$k]['thumb'] = $photoList[$item['product']['main_photo']]['url'] ?? '';
                    }

                    /*  brand */
                    if (!empty($item['product']['brand'])) {
                        $order_item[$k]['brand_id'] = $item['product']['brand']['id'];
                        $order_item[$k]['brand_name'] = $item['product']['brand']['name'];
                        $order_item[$k]['brand_icon'] = $item['product']['brand']['brand_icon'];
                    }

                    $order_item[$k]['condition'] = $item['product']['condition'];
                    $order_item[$k]['expiration_date'] = $item['product']['expiration_date'];

                    $order[$key]['unit'] = $item['product']['unit'];
                    $order[$key]['hashrate'] = $item['product']['hashrate'] . ' ' . $item['product']['unit'];
                    $order[$key]['power'] = $item['product']['power'];

                    $order_item[$k]['estimated_ship_date'] = $item['product']['estimated_ship_date'];
                    $order_item[$k]['weight'] = $item['product']['weight'];
                }
            }
        }

        $order[$key]['item'] = array_values($order_item);
        unset($result['data']);
        $result['list'] = $order;
        return Basic::data(0, 'common.success', $result);
    }


    /**
     *  订单详情
     */
    public function detail($param)
    {
        $where['user_id'] = $param['user_id'];
        $where['order_no'] = $param['orderNo'];
        $common = new \app\api\service\Common();
        $result = ModelOrder::with([
            'item' => function ($query) {
                $query->with([
                    'product' => function ($query) {
                        return $query->with([
                            'brand' => function ($query) {
                                return $query->field('id,name,image');
                            },
                            'category' => function ($query) {
                                return $query->field('id,name');
                            },
                        ])->field('id,powerline_specs,cname,category,brand,condition,expiration_date,hashrate,computing_unit,power,main_photo,photo,type,describe,estimated_ship_date,weight');
                    },
                    'warehouse' => function ($query) {
                        return $query->field('id,show_name,name,pickup_address');
                    }

                ])->where('is_del', '=', 0)->where('quantity', '>', 0)
                    ->field('id,order_id,product_id,warehouse_id,first_leg_logistics_fee,original_price,actual_price,price_selected_currency,is_futures,quantity,create_time,arrival_date');
            },
            'payment_record' => function ($query) {
                $query->with([
                    'images' => function ($query) {
                        $query->field('id,url');
                    }
                ])->field('id,order_id,payment_method,paid_amount,payment_method_name,pay_type,pay_time,pay_amount,pay_code,create_time,reviewer,reviewer_time,transfer_voucher_id,status,notes,order_no,user_id')->where('order_type', 'order');
            }
        ])
            //->field('id,order_no,user_id,first_name,last_name,create_time,country_name,city_name,pay_method_name,total_amount,pay_amount,pay_status,status,logistics_fee,source,tax_fee')
            ->where($where)->find();


        if (empty($result)) {
            return Basic::data(1, 'order.orderNotExist');
        }

        $result = $result->toArray();
        $photoidsArr = [];
        $photoList = [];
        if($result['item']){
            foreach ($result['item'] as $productData ){
                if(!empty($productData['product']['main_photo']) ){
                    $photoidsArr[]=$productData['product']['main_photo'];
                }
                if ($productData['product']['type'] == 2 && !empty($productData['product']['photo'])) {
                    $photoidsArr[] = explode(',', $productData['product']['photo'])[0];
                }
            }
            $imageModel = new Images();
            if($photoidsArr){
                $photoList = $imageModel->getImagesByIds($photoidsArr);

                // 将数组转换为以ID为下标的结构
                $photoList = array_column($photoList, null, 'id');
            }

        }


        /* 查询物流订单 */
        $logisticsOrderOn = [];
        $logisticsOrder = [];
        $status = $result['status'] ?? null;
        if (in_array($status, [40, 50, 100], true)) { // 严格模式
            $logisticsOrder = LogisticsOrderItem::with(['logisticsOrder' => function ($query) {
                return $query->field('id,logistics_no,company_id');
            }])->where('order_id', $result['id'])->field('id,logistics_order_id,product_id,warehouse_id,number')->select();

            /* 物流订单 */
            if ($logisticsOrder) {
                $logisticsOrder = $logisticsOrder->toArray();
                foreach ($logisticsOrder as $item) {
                    $key = implode('_', [$item['product_id'], $item['warehouse_id']]);
                    $logisticsOrderOn[$key] = $item['logisticsOrder']['logistics_no'];
                }
            }
        }

        /* 商品明细 */
        $item_list = [];
        $shipped_list = [];
        $paid_list = [];
        foreach ($result['item']  as $key => $item) {
            $key = implode('_', [
                $item['product_id'],
                $item['warehouse_id'],
                $item['arrival_date'],
                $item['is_futures']
            ]);

            /* 合并 */
            if (isset($item_list[$key])) {
                $item_list[$key]['quantity'] = Calculate::pricecalc($item_list[$key]['quantity'], '+', $item['quantity'], 0);
                continue;
            }

            $item_list[$key]['id'] = $item['id'];
            $item_list[$key]['original_price'] = $item['original_price'];
            $item_list[$key]['actual_price'] = $item['actual_price'];
            $item_list[$key]['first_leg_logistics_fee'] = $item['first_leg_logistics_fee'];
            $item_list[$key]['is_futures'] = $item['is_futures'];
            $item_list[$key]['quantity'] = $item['quantity'];
            $item_list[$key]['product_id'] = $item['product_id'];
            $item_list[$key]['arrival_date'] = $item['arrival_date'];
            $item_list[$key]['warehouse_id'] = $item['warehouse_id'];
            $item_list[$key]['warehouse_name'] = $common->singleTranslate($item['warehouse']['name'],$param['lang']);
            $item_list[$key]['warehouse_show_name'] = $common->singleTranslate($item['warehouse']['show_name'],$param['lang']);
            $item_list[$key]['pickup_address'] = $item['warehouse']['pickup_address'];
            $item_list[$key]['price_selected_currency'] = $item['price_selected_currency'];

            /* 商品详情 */
            if ($item['product']) {

                $item_list[$key]['name'] = $common->singleTranslate($item['product']['cname'],$param['lang']);
                $item_list[$key]['powerline_specs'] = $item['product']['powerline_specs'];

                /* 分类 */
                if (!empty($item['product']['category'])) {
                    $item_list[$key]['category_id'] = $item['product']['category']['id'];
                    $item_list[$key]['category_name'] = $item['product']['category']['name'];
                }

                /*  brand */
                if (!empty($item['product']['brand'])) {
                    $item_list[$key]['brand_id'] = $item['product']['brand']['id'];
                    $item_list[$key]['brand_name'] = $common->singleTranslate($item['product']['brand']['name'],$param['lang']) ;
                    $item_list[$key]['brand_icon'] = $item['product']['brand']['brand_icon'];
                }

                /* 缩略图 */
                if (isset($item['product']['main_photo']) && !empty($item['product']['main_photo'])) {
                    $item_list[$key]['thumb'] = $photoList[$item['product']['main_photo']]['url'];
                } elseif($item['product']['type'] == 2 && isset($item['product']['photo']) && $item['product']['photo']) {

                    $photoKey = explode(',',$item['product']['photo'])[0];
                    $item_list[$key]['thumb'] =$photoList[$photoKey]['url'];
                }

                $item_list[$key]['condition'] = $item['product']['condition'];
                $item_list[$key]['expiration_date'] = $item['product']['expiration_date'];

                $item_list[$key]['hashrate'] = $item['product']['hashrate'];
                $item_list[$key]['computing_unit'] = $item['product']['computing_unit'];
                $item_list[$key]['power'] = $item['product']['power'];

                $item_list[$key]['unit'] = $item['product']['unit'];
                $item_list[$key]['hashrate'] = $item['product']['hashrate'] . ' ' . $item['product']['unit'];
                $item_list[$key]['power'] = $item['product']['power'];

                $item_list[$key]['estimated_ship_date'] = $item['product']['estimated_ship_date'];
                $item_list[$key]['weight'] = $item['product']['weight'];
            }

            /* 物流订单号 */
            $logistics_key = implode('_', [$item['product_id'], $item['warehouse_id']]);
            if (isset($logisticsOrderOn[$logistics_key])) {
                $item_list[$key]['logistics_no'] = $logisticsOrderOn[$logistics_key];
            } else {
                $item_list[$key]['logistics_no'] = '';
            }
        }
        $shipped_base = [];
        $product_total = [];
        #处理发货或者未发货明细  初始化数据备用
        foreach ($item_list as $il) {
            #为了取出所有商品数据 发货未发货数据
            $product_total[$il['product_id']]['name'] = $il['name'];
            $product_total[$il['product_id']]['thumb'] = $il['thumb'];
            $product_total[$il['product_id']]['status'] =$common->singleTranslate('Paid',$param['lang']) ;
            $num = $product_total[$il['product_id']]['sum_quantity'] ?? 0;
            $total_il = $product_total[$il['product_id']]['Subtotal'] ?? 0;
            $product_total[$il['product_id']]['sum_quantity'] = $num + $il['quantity'];
            $line_total = Calculate::pricecalc($il['quantity'], '*', $il['price_selected_currency'], 2);
            $product_total[$il['product_id']]['Subtotal'] = Calculate::pricecalc($line_total, '+', $total_il, 2);
            $il_key = implode('_', [
                $il['product_id'],
                $il['warehouse_id']
            ]);
            if ($il['is_futures'] == 0) {
                $shipped_base[$il_key] = $il;
            }
        }
        #处理发货数据
        [$shipped_list, $shipped_total] = $this->getShipmentStatus($shipped_base, $logisticsOrder);
        #聚合发货数据
        $shipped_list_base = [];
        foreach ($shipped_list as $ship_iterm) {

            $shipped_list_base[$ship_iterm['logistics_no']]['product'][] = [
                'name' => $ship_iterm['name'],
                'thumb' => $ship_iterm['thumb'],
                'status' => $common->singleTranslate('Shipped',$param['lang']),
                'quantity' => $ship_iterm['quantity'],
                'Subtotal' => $ship_iterm['Subtotal'],
            ];

            $shipped_list_base[$ship_iterm['logistics_no']]['logistics_no'] = $ship_iterm['logistics_no'];
            $shipped_list_base[$ship_iterm['logistics_no']]['company_name'] = $ship_iterm['company_name'];
        }

        $shipped_list = array_values($shipped_list_base);
        #处理未发货数据 $paid_list
        foreach ($product_total as $key => $paid) {
            if (!isset($shipped_total[$key])) {
                $paid['quantity'] = $paid['sum_quantity'];
                $paid_list[] = $paid;
                continue;
            }
            if ($shipped_total[$key]['quantity'] < $paid['sum_quantity']) {
                $paid['quantity'] =  Calculate::pricecalc($paid['sum_quantity'], '-', $shipped_total[$key]['quantity'], 0);
                $paid['Subtotal'] =  Calculate::pricecalc($paid['Subtotal'], '-', $shipped_total[$key]['total'], 2);
                $paid_list[] = $paid;
            }
        }

        /* 转账显示银行信息 */
        $PaymentMethod = new PaymentMethod();
        $result['payment_information'] = $PaymentMethod->getPaymentInformation();

        /* 支付方式 */
        $PaymentMethod = new PaymentMethod();
        $result['payment_method_list'] = $PaymentMethod->getPaymentMethodList($param);
        foreach ($result['payment_method_list'] as &$payment_method_list)
        {
            $payment_method_list['name'] = $common->singleTranslate($payment_method_list['name'],$param['lang']);
        }

        /* 支付凭证 */
        $voucher = [];
        if (isset($result['payment_record'])) {
            foreach ($result['payment_record'] as $k => $voucherItem) {
                if (isset($voucherItem['images'])) {
                    $voucherItem['payment_voucher_url'] = $voucherItem['images']['url'];
                    unset($voucherItem['images']);
                }
                $voucher[$k] = $voucherItem;
            }
        }
        $result['payment_record'] = $voucher;
        $result['shipped_list'] = $shipped_list;
        $result['paid_list'] = $paid_list;
        if($result['status_text']){
            $result['status_text'] = $common->singleTranslate($result['status_text'],$param['lang']);
        }
        if($result['delivery_method_text']){
            $result['delivery_method_text'] = $common->singleTranslate($result['delivery_method_text'],$param['lang']);
        }
        if($result['pay_method_name']){
            $result['pay_method_name'] = $common->singleTranslate($result['pay_method_name'],$param['lang']);
        }
        /*  */
        unset($result['item']);
        $result['list'] = array_values($item_list);
        return Basic::data(0, 'common.success', $result);
    }
    #根据发货明细 聚合 订单行的发货状态
    private function getShipmentStatus($item, $logisticsOrder): array
    {
        $shipped_list = [];
        $shipped_total = [];
        if (!empty($logisticsOrder)) {
            foreach ($logisticsOrder as $logistics) {
                $il_key = implode('_', [
                    $logistics['product_id'],
                    $logistics['warehouse_id']
                ]);
                #为了取出所有商品数据 发货未发货数据
                $num = $shipped_total[$logistics['product_id']]['quantity'] ?? 0;
                $total_il = $shipped_total[$logistics['product_id']]['total'] ?? 0;
                $shipped_total[$logistics['product_id']]['quantity'] = $num + $logistics['number'];
                $line_total = Calculate::pricecalc($logistics['number'], '*', $item[$il_key]['price_selected_currency'], 2);
                $shipped_total[$logistics['product_id']]['total'] = Calculate::pricecalc($line_total, '+', $total_il, 2);


                $item[$il_key]['status'] = 'shipped';
                $item[$il_key]['logistics_no'] = $logistics['logisticsOrder']['logistics_no'] ?? '';
                $company_id = $logistics['logisticsOrder']['company_id'] ?? '';
                $company_name = '';
                if ($company_id) {
                    $company_name = LogisticsCompany::where('id', $company_id)->value('name');
                }
                $item[$il_key]['company_name'] = $company_name;
                $item[$il_key]['quantity'] = $logistics['number'];
                $item[$il_key]['Subtotal'] = Calculate::pricecalc($logistics['number'], '*', $item[$il_key]['price_selected_currency'], 2);

                $shipped_list[] = $item[$il_key];
            }
        }

        return [$shipped_list, $shipped_total];
    }

    /**
     *  删除支付凭证
     */
    public function VoucherRemove($param)
    {
        $where['user_id'] = $param['user_id'];
        $where['id'] = $param['id'];

        $PaymentVoucher = ModelOrderPayment::where($where)->field('id,payment_method,status')->find();

        if (empty($PaymentVoucher)) {
            return Basic::data(1, 'order.voucherNotExist');
        }

        if ($PaymentVoucher->payment_method !== '3') {
            return Basic::data(1, 'order.voucherMethodError');
        }

        if ($PaymentVoucher->status !== '00') {
            return Basic::data(1, 'order.voucherStatusError');
        }

        $result = $PaymentVoucher->delete();
        if ($result) {
            return Basic::data(0, 'common.success');
        } else {
            return Basic::data(1, 'common.error');
        }
    }

    /**
     *  拉起支付
     */
    public function payment($param)
    {
        try {
            // 1. 查询并验证订单
            $order = ModelOrder::where([
                'user_id' => $param['user_id'],
                'order_no' => $param['orderNo'],
                'is_del' => 0
            ])->find();

            if (empty($order)) {
                return Basic::data(1, 'order.orderNotExist');
            }

            // 2. 检查支付状态
            if ($order->pay_status == 3) {
                return Basic::data(1, 'order.orderPayStatusError');
            }

            $OrderPayment = new OrderPayment();

            // 3. 根据支付方式处理
            // 凭证支付
            if ($param['payment_method'] == 3) {
                return $OrderPayment->goPay($order, $param);
            }

            // 在线支付
            if ($param['payment_method'] < 3) {
                // 查询最近的支付记录
                $order_payment = ModelOrderPayment::where([
                    'order_id' => $order->id,
                    'payment_method' => $param['payment_method'],
                ])
                    ->where('status', 'in', ['00', '01', '02', '03'])
                    ->field('id,order_no,payment_url,order_type,create_time')
                    ->order('create_time', 'desc')
                    ->find();

                // 无支付记录，创建新支付
                if (empty($order_payment)) {
                    return $OrderPayment->goPay($order, $param);
                }

                // 检查支付记录是否过期（48小时）
                $termValidity = time() - strtotime($order_payment->create_time);
                if ($termValidity > 3600 * 48) {
                    return $OrderPayment->goPay($order, $param);
                }

                // 返回现有的支付信息
                return Basic::data(0, 'common.success', [
                    'order_type' => $order_payment->order_type,
                    'order_no' => $order_payment->order_no,
                    'payment_url' => $order_payment->payment_url
                ]);
            }

            return Basic::data(1, 'order.orderPaymentMethodError');
        } catch (\Exception $e) {
            return Basic::data(1, $e->getMessage());
        }
    }

    /**
     *  获取订单状态列表
     */
    public function getStatusList($lang)
    {
        $ModelOrder = new ModelOrder();
        $StatusList =  $ModelOrder->getFieldEnum('all');
        $common = new \app\api\service\Common();
        $Status[] = [
            'name' => Lang::get('status.all'),
            'value' => 'all'
        ];

        foreach ($StatusList['status'] as $key => $value) {
            if (array_search($key, ['all', 10, 20, 30, 50, 60, 70, 100], true)) {
                $Status[] = [
                    'name' => Lang::get($value),
                    'value' => strval($key)
                ];
            }
        }
        foreach ($Status as &$status) {
            $status['name'] = $common->singleTranslate($status['name'],$lang);
        }

        return Basic::data(0, 'common.success', $Status);
    }


    /**
     *  订单商品名称
     */
    public function getProductInfo($order)
    {
        $result = OrderItem::with(['product' => function ($query) {
            $query->field('id,cname,computing_unit');
        }])->field('id,order_id,product_id,quantity')->where('order_id', $order->id)->select();

        if (!$result) {
            $data['name'] = '';
            $data['description'] = '';
            return $data;
        }

        $result = $result->toArray();

        $count = 0;
        $description = '';
        $str = '';
        foreach ($result as $key => $item) {
            $count = Calculate::pricecalc($count, '+', $item['quantity'], 0);
            if ($key  == 0) {
                $data['name'] = $item['product']['cname'];
            }
            $str =  ' Total for (' . $count . ') products';
            $description .= $item['product']['cname'] . ' (' . $item['quantity'] . '),';
        }

        $data['name'] = $data['name'] . $str;
        $data['description'] = substr($description, 0, -1) . $str;
        return $data;
    }


    /**
     *   订单锁定库存
     */
    public function Inventorylocking($order, $type)
    {
        $Inventory = new Inventory();
        switch ($type) {
            case 'order':
                $orderItem = OrderItem::where('order_id', $order->id)->field('quantity,product_id,warehouse_id,arrival_date,is_futures')->select()->toArray();
                return $Inventory->locking($orderItem, $type);
                break;
            case 'wholesale':
                $orderItem = WholesalOrderItem::where('order_id', $order->id)->field('id,quantity,product_id,warehouse_id,arrival_date,is_futures')->select()->toArray();
                return $Inventory->locking($orderItem, $type);
                break;

            default:
                throw new ThrowException([
                    'message' => '锁定库存，订单类型错误'
                ]);
        }
    }

    /**
     *  订单释放锁定库存
     */


    /**
     *
     */
    public function reduce($order)
    {

        //                 'productid' => 22,
        //                'wid' => 7,
        //                'num' => 1200,
        //                'arrival_date' => '2024-10-23',
        //                'is_futures' => 2,
        //            ]

        $result = ModelOrder::with([
            'item' => function ($query) {
                $query->with([])->field('order_id,product_id,warehouse_id,quantity,arrival_date,is_futures');
            },
        ])->field('id,order_type')
            ->where('id', '358')->find()->toArray();

        // $orderItem = OrderItem::where('order_id','312')->select();


        //
        $Inventory = new Inventory();
        $Inventory->unlock($result['item']);
        // $result = $Inventory->reduce($result['item'],'order',$result['id'],'用户下单','经销商下单');

        if ($result) {
            return Basic::data(0, 'common.success');
        } else {
            return Basic::data(1, 'common.error');
        }
    }


    /**
     *  获取仓库地址
     */
    public function getwarehouseAddress($param)
    {


        foreach ($param['product'] as $value) {
            $warehouse_id[$value['wid']] = $value['wid'];
        }

        if (count($warehouse_id) > 1) {
            return Basic::data(1, 'order.multipleWarehousesUnable');
        }

        $warehouse_id = array_shift($warehouse_id);
        $Warehouse = Warehouse::where('id', $warehouse_id)->field('pickup_address')->find();


        $pickup_address = $Warehouse->pickup_address;
        if (empty($pickup_address)) {
            $pickup_address = ' ';
        }

        return Basic::data(0, 'ok', $pickup_address);
    }


    /**
     *  订单取消
     */
    public function cancel($param)
    {
        $where[] = ['user_id', '=', $param['user_id']];
        $where[] = ['order_no', '=', $param['orderNo']];

        $order = ModelOrder::where($where)->find();

        if (!$order) {
            return Basic::data(1, 'order.orderNotExist');
        }

        /* 该订单已取消 */
        if ($order->status == 70) {
            return Basic::data(1, 'order.orderStatusError');
        }

        /* 订单大于30 的状态无法取消 */
        if ($order->status > 30) {
            return Basic::data(1, 'order.orderStatusError');
        }
        /* 支付状态 */

        if ($order->pay_status != 1) {
            return Basic::data(1, 'order.orderStatusError');
        }
        $message = '';
        $result = Db::transaction(function () use ($order, $message) {
            if ($order->order_type == 2) {
                // 如果为经销商发货单 释放经销商资产
                $orderItems = $order->item->toArray();
                if (count($orderItems) == 0) {
                    return  $message = '订单商品不存在';
                }
                $wholesal_id = reset($orderItems)['wholesal_id'];
                foreach ($orderItems as $item) {
                    $wholesalWhere = [
                        'order_id' => $wholesal_id,
                        'product_id' => $item['product_id'],
                        'warehouse_id' => $item['warehouse_id'],
                        'arrival_date' => $item['arrival_date'],
                        'is_futures' => $item['is_futures']
                    ];
                    $oWholesalOrderItem = WholesalOrderItem::where($wholesalWhere)->select();
                    if (!$oWholesalOrderItem) {
                        return  $message = '订单商品不存在';
                    }
                    $total_qty = $oWholesalOrderItem[0]->quantity;
                    if ($total_qty < $item['pending_quantity']) {
                        return  $message = '订单商品数量不足';
                    }
                    $surplus = 0; // 剩余数量
                    foreach ($oWholesalOrderItem as $val) {
                        $quantity = $surplus == 0 ? $item['pending_quantity'] : $surplus;
                        if ($val->lock_qty >= $quantity) {
                            $val->lock_qty = $val->lock_qty - $item['pending_quantity'];
                            $surplus = 0;
                        } elseif ($val->lock_qty < $item['pending_quantity']) {
                            $val->lock_qty = 0;
                            $surplus = $item['pending_quantity'] - $val->lock_qty;
                        }
                        $val->save();
                    }
                }
            }
            /* 取消订单 */
            $order->status = 70;
            $order->save();
            return $message;
        });

        if (empty($message)) {

            /* 修改GoAffPro订单状态 */
            $GoAffPro = new GoAffPro();
            $GoAffPro->updateAffiliateOrder(false, $order->id);

            $Business = new BusinessLog();
            $Business->logOperation($order->id, 'order', '取消订单', $order->order_no);

            $partnerArr = $order->partner ? array_filter(explode(',', $order->partner)) : [];
            $recipients = array_merge([$order->owner, $order->signatory, ...$partnerArr]);
            $notificationService = new CompleteNotificationService();
            $notificationService->send('order_cancel', $order->toArray(), $recipients);

            return Basic::data(0, 'common.success');
        } else {
            return Basic::data(1, 'common.error');
        }
    }



    /**
     *  修改地址
     */
    public function setAddress($param)
    {
        $where[] = ['user_id', '=', $param['user_id']];
        $where[] = ['order_no', '=', $param['orderNo']];

        $result = ModelOrder::where($where)->find();
        #判断地址是否有更新
        $param['scene'] == 1 ? $order_address = $result->address_id : $order_address = $result->billing_address_id;
        if ($order_address ==  $param['address_id']) {
            return Basic::data(0, 'common.success');
        }
        if (!$result) {
            return Basic::data(1, 'order.orderNotExist');
        }
        /* 订单大于30 的状态无法取消 */
        if ($result->status >= 30) {
            return Basic::data(1, 'order.orderStatusError');
        }
        /* 支付状态 */
        if ($result->pay_status == 3) {
            return Basic::data(1, 'order.orderStatusError');
        }
        /* 查询地址 */
        $address_where[] = ['id', '=', $param['address_id']];
        $address_where[] = ['user_id', '=', $param['user_id']];
        $address = AddressModel::where($address_where)->find();
        if (!$address) {
            return Basic::data(1, 'address.addressNotExist');
        }
        switch ($param['scene']) {
            case 1:
                $result->address_id = $address->id;
                $result->first_name = $address->first_name;
                $result->last_name = $address->last_name;
                $result->email = $address->email;
                $result->country_id = $address->country_id;
                $result->city_id = $address->city_id;
                $result->city_name = $address->city_name;
                $result->country_name = $address->country_name;
                $result->zip_code = $address->zip_code;
                $result->state = $address->state;
                $result->state_id = $address->state_id;
                $result->company = $address->company;
                $result->phone = $address->phone;
                $result->address = $address->address;
                $result->address2 = $address->address2;
                $scene_name = '订单收货地址修改';
                break;
            case 2:
                $result->billing_address_id = $address->id;
                $result->billing_first_name = $address->first_name;
                $result->billing_last_name = $address->last_name;
                $result->billing_email = $address->email;
                $result->billing_country_id = $address->country_id;
                $result->billing_city_id = $address->city_id;
                $result->billing_city_name = $address->city_name;
                $result->billing_zip_code = $address->country_name;
                $result->billing_state = $address->state;
                $result->billing_state_id = $address->state_id;
                $result->billing_company = $address->company;
                $result->billing_phone = $address->phone;
                $result->billing_address = $address->address;
                $result->billing_address2 = $address->address2;
                $scene_name = '订单账单地址修改';
                break;
            default:
                return Basic::data(1, 'common.error');
        }
        $update_result = Db::transaction(function () use ($address, $result, $param) {
            if ($param['scene'] == 1) {
                $ccNameId = $address->country_id;
                $to_param = [];
                $to_param['to_nation'] = $ccNameId;
                $to_param['prescription'] = $result->prescription;
                $to_param['terms'] = $result->delivery_terms;
                $to_param['product_list'] = [];
                $order_iterm = OrderItem::where('order_id', $result->id)->select()->toArray();
                $pids = array_column($order_iterm, 'product_id');
                $productInfo = ProductModel::where('id', 'in', $pids)->field('id,billing_weight,free_shipping,apply_rules')->select()->toArray();
                $productInfo = array_column($productInfo, null, 'id');
                $product_list = [];
                foreach ($order_iterm as $k => $p) {
                    $product_list[$k]['id'] = $p['product_id'];
                    $product_list[$k]['wid'] = $p['warehouse_id'];
                    $product_list[$k]['billing_weight'] = $productInfo[$p['product_id']]['billing_weight'] ?? '';
                    $product_list[$k]['free_shipping'] = $productInfo[$p['product_id']]['free_shipping'] == 0 ? false : true;
                    $product_list[$k]['apply_rules'] = $productInfo[$p['product_id']]['apply_rules']  == 0 ? false : true;
                    $product_list[$k]['num'] = $p['quantity'];
                }
                $to_param['product_list'] = $product_list;
                $fee = (new LogisticsRules())->getLogisticsFee($to_param);

                if (isset($fee['code']) && $fee['code'] != 0) {
                    return false;
                }
                if (!isset($fee['data']['logistics_fee'])) {
                    return false;
                }
                $new_logistics = $fee['data']['logistics_fee'];
                #运费不相等 则更新运费  和总价
                if ($new_logistics != $result->logistics_fee) {
                    $result->logistics_fee = $new_logistics;
                    $result->total_amount = Calculate::pricecalc($result->logistics_fee, '+', $result->product_total_amount, 2);
                    #如果已经支付价格大于新的订单总价 需要做后续操作
                    if ($result->pay_amount >= $result->total_amount) {
                        $result->pay_status = 3;
                        $result->status = 30;
                        if ($result->order_type !== 2) {
                            foreach ($order_iterm as $value) {
                                // 完全支付后 更新库存盘点
                                WarehouseAdmin::productSoldStat($value['product_id'], $value['warehouse_id'], 0, $value['quantity'], $value['quantity']);
                            }
                        }
                    }
                }
            }
            $result->save();
            return true;
        });
        if ($update_result) {
            $Business = new BusinessLog();
            $Business->logOperation($result->id, 'order', $scene_name, $result->order_no);
            return Basic::data(0, 'common.success');
        } else {
            return Basic::data(1, 'common.error');
        }
    }
}
